package org.cxy.monitor;

import jakarta.annotation.PostConstruct;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
@EnableConfigurationProperties(MonitorProperties.class)
public class MonitorAspect {

    @Autowired(required = false)
    private MonitorProperties properties;

    @Autowired(required = false)
    private MonitorService monitorService;

    @PostConstruct
    public void init() {
        System.out.println("=== MonitorAspect 初始化完成 ===");
        if (properties != null) {
            System.out.println("监控开关: " + properties.isEnabled());
            System.out.println("监控包: " + Arrays.toString(properties.getBasePackages()));
            System.out.println("慢方法阈值: " + properties.getSlowThreshold() + "ms");
        } else {
            System.out.println("MonitorProperties 未配置，使用默认值");
        }
    }

    // 使用相对宽泛但不会引起循环依赖的切点
    // 这里我们监控所有 Spring 组件，但在运行时进行包路径过滤
    @Pointcut("within(@org.springframework.stereotype.Component *) || " +
            "within(@org.springframework.stereotype.Service *) || " +
            "within(@org.springframework.web.bind.annotation.RestController *)")
    public void springComponents() {}

    @Around("springComponents()")
    public Object monitorMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 检查是否启用监控
        if (properties == null || monitorService == null || !properties.isEnabled()) {
            return joinPoint.proceed();
        }

        // 获取完整的类名
        String className = joinPoint.getTarget().getClass().getName();

        // 检查是否在配置的包路径内
        if (!isInMonitoredPackages(className)) {
            return joinPoint.proceed();
        }

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getName();
        String fullMethodName = joinPoint.getTarget().getClass().getSimpleName() + "." + methodName;

        long startTime = System.currentTimeMillis();
        Object result = null;
        boolean success = true;

        try {
            monitorService.beforeExecute(fullMethodName, joinPoint.getArgs());
            result = joinPoint.proceed();
            return result;
        } catch (Throwable throwable) {
            success = false;
            monitorService.onError(fullMethodName, throwable);
            throw throwable;
        } finally {
            long cost = System.currentTimeMillis() - startTime;
            monitorService.afterExecute(fullMethodName, result, cost, success);

            // 记录慢方法
            if (cost > properties.getSlowThreshold()) {
                monitorService.slowMethod(fullMethodName, cost, properties.getSlowThreshold());
            }
        }
    }

    /**
     * 检查类是否在监控的包路径内
     */
    private boolean isInMonitoredPackages(String className) {
        // 如果没有配置包路径，默认不监控任何方法（避免循环依赖）
        if (properties.getBasePackages() == null || properties.getBasePackages().length == 0) {
            return false;
        }

        for (String basePackage : properties.getBasePackages()) {
            if (className.startsWith(basePackage)) {
                return true;
            }
        }
        return false;
    }
}